#ifndef SIMULATOR
#include "wifi.h"
#include "main.h"
#include "messager.h"

// ##
#define LOG_TAG     "wifi"
#include "ulog.h"

/* Update SSID and PASSWORD with own Access point settings */
#define DEMO_SSID   "HMBJ"
#define DEMO_PSWD   "hmbj001001"

const WIFI_APConfig_t ap_config =
{
    .SSID = DEMO_SSID,
    .PSWD = DEMO_PSWD,
    .Ecn = WIFI_ECN_WPA_WPA2_PSK,
};


uint8_t RemoteIP[] = {210, 72, 145, 44};
#define RemotePORT	8002

#define WIFI_WRITE_TIMEOUT 10000
#define WIFI_READ_TIMEOUT  10000

#define CONNECTION_TRIAL_MAX          10

uint8_t  IP_Addr[4];
uint8_t TxData[] = "STM32 : Hello!";
int32_t Socket = -1;
uint16_t Datalen;
int32_t ret;
int16_t Trials = CONNECTION_TRIAL_MAX;
uint8_t RxData [500];

// ##
static uint32_t list_mail[] =
{
    MSG_WIFI_ON,
    MSG_WIFI_OFF,
    MSG_WIFI_CONNECT,
    MSG_WIFI_DISCONNECT,
};

#define MAIL_LIST_DEPTH (sizeof(list_mail) / sizeof(uint32_t))

// ##
static mMessager_t mail_box;

// ##
static uint32_t stack_last = 0;
static uint32_t stack_cur = 0;

// ##
void thread_wifi(const void *argument)
{
    // ##
    msg_t msg;
    uint8_t content[256];
    uint32_t len = 0;

    // Initialize LED
    BSP_LED_Init(LED2);

    // ##
    mail_box = messager_create(MAIL_LIST_DEPTH);

    messager_register(mail_box, &list_mail[0], MAIL_LIST_DEPTH);

    // ##
    log_info("%s starts to run...", __func__);

    for (;;)
    {
        if (messager_recv(mail_box, &msg, content, &len, sizeof(content)) != RESULT_ERR)
        {
            switch (msg)
            {
                case MSG_WIFI_ON:
                {
                    // Initialize  WIFI module
                    if(WIFI_Init() ==  WIFI_STATUS_OK)
                    {
                        log_info("> WIFI Module Initialized.");

                        // ##
                        char *module_info = (char *)pvPortMalloc(64);
                        if(module_info != NULL)
                        {
                            WIFI_GetModuleName(module_info);
                            log_info("> es-wifi module name : %s.", module_info);
                            WIFI_GetModuleFwRevision(module_info);
                            log_info("> es-wifi module fw version : %s.", module_info);
                            WIFI_GetModuleID(module_info);
                            log_info("> es-wifi module id : %s.", module_info);
                            WIFI_GetMAC_Address((uint8_t *)module_info);
                            log_info("> es-wifi module MAC Address : %X:%X:%X:%X:%X:%X",
                                    module_info[0], module_info[1], module_info[2],
                                    module_info[3], module_info[4], module_info[5]);
                            vPortFree(module_info);

                            // ##
                            messager_mail(MSG_WIFI_CONNECT, (void *)&ap_config, sizeof(WIFI_APConfig_t));
                        }
                    }
                    else
                    {
                        log_info("> ERROR : WIFI Module cannot be initialized..");
                    }
                    break;
                }
                case MSG_WIFI_OFF:
                {
                    break;
                }
                case MSG_WIFI_CONNECT:
                {
                    WIFI_APConfig_t *ap_config = (WIFI_APConfig_t *)content;

                    log_info("> es-wifi module is trying to connect to %s...", ap_config->SSID);

                    if(WIFI_Connect(ap_config->SSID, ap_config->PSWD, ap_config->Ecn) == WIFI_STATUS_OK)
                    {
                        log_info("> es-wifi module connected to %s.", ap_config->SSID);
                        if(WIFI_GetIP_Address(IP_Addr) == WIFI_STATUS_OK)
                        {
                            log_info("> es-wifi module got IP Address : %d.%d.%d.%d",
                                        IP_Addr[0], IP_Addr[1], IP_Addr[2], IP_Addr[3]);


                            WIFI_APs_t *wifi_aps = pvPortMalloc(sizeof(WIFI_APs_t));
                            if(wifi_aps != NULL)
                            {
                                if(WIFI_ListAccessPoints(wifi_aps, 10) == WIFI_STATUS_OK)
                                {
                                    uint8_t i = 0;
                                    for(i = 0; i < 10; i ++)
                                    {
                                        log_info("> es-wifi ap[%d] : %s, %d, %d", i, wifi_aps->ap[i].SSID,
                                                                                wifi_aps->ap[i].RSSI,
                                                                                wifi_aps->ap[i].Ecn);
                                    }
                                }
                                else
                                {
                                    log_info("> es-wifi : failrf to list APs.");
                                }

                                vPortFree(wifi_aps);
                            }

                            #if 0
                            log_info("> Trying to connect to Server: %d.%d.%d.%d:%d ...",
                                        RemoteIP[0],
                                        RemoteIP[1],
                                        RemoteIP[2],
                                        RemoteIP[3],
                                        RemotePORT);

                            while (Trials--)
                            {
                                if( WIFI_OpenClientConnection(0, WIFI_TCP_PROTOCOL, "TCP_CLIENT", RemoteIP, RemotePORT, 0) == WIFI_STATUS_OK)
                                {
                                    log_info("> TCP Connection opened successfully..");
                                    Socket = 0;
                                    break;
                                }
                            }
                            if(Socket == -1)
                            {
                                log_info("> ERROR : Cannot open Connection.");
                                BSP_LED_On(LED2);
                            }
                            #endif
                        }
                        else
                        {
                            log_info("> ERROR : es-wifi module CANNOT get IP address.");
                            BSP_LED_On(LED2);
                        }
                    }
                    else
                    {
                        log_info("> ERROR : es-wifi module NOT connected.");
                        BSP_LED_On(LED2);
                    }
                    break;
                }
                case MSG_WIFI_DISCONNECT:
                {
                    break;
                }
                default:
                {
                    log_info("msg %d is not listed, please check it.", msg);
                    break;
                }
            }

            // ##
            stack_cur =  uxTaskGetStackHighWaterMark(osThreadGetId());

            if (stack_cur != stack_last)
            {
                stack_last = stack_cur;

                log_info("[%s] %ld bytes left in stack %ld bytes", osThreadGetName(osThreadGetId()), stack_cur * sizeof(StackType_t), THREAD_ROUTER_STACK_DEPTH * sizeof(StackType_t));
            }
        }
        else
        {
            log_error("failed to receive from mail_box.");
        }
    }
}

#endif